<?php

class SpellCorrectorTwoWords {
	private static $NWORDS;
	private static $NWORDSTwo;

	private static function edits1($word) {
		$alphabet = 'abcdefghijklmnopqrstuvwxyz';
		//$alphabet = 'аәбвгғдеёжзийкқлмнңоөпрстуұүфхһцчшщъыіьэюя';
		$alphabet = str_split($alphabet);
		$n = strlen($word);
		$edits = array();
		for($i = 0 ; $i<$n;$i++) {
			$edits[] = substr($word,0,$i).substr($word,$i+1); 		//deleting one char
			foreach($alphabet as $c) {
				$edits[] = substr($word,0,$i) . $c . substr($word,$i+1); //substituting one char
			}
		}
		for($i = 0; $i < $n-1; $i++) {
			$edits[] = substr($word,0,$i).$word[$i+1].$word[$i].substr($word,$i+2); //swapping chars order
		}
		for($i=0; $i < $n+1; $i++) {
			foreach($alphabet as $c) {
				$edits[] = substr($word,0,$i).$c.substr($word,$i); //inserting one char
			}
		}
		return $edits;
	}
	
	private static function known_edits2($word) {
		$known = array();
		foreach(self::edits1($word) as $e1) {
			foreach(self::edits1($e1) as $e2) {
				if(array_key_exists($e2,self::$NWORDS)) $known[$e2] = $e2;				
			}
		}
		return $known;
	}
	
	private static function known(array $words) {
		$known = array();
		foreach($words as $w) {
			if(array_key_exists($w,self::$NWORDS)) {
				$known[$w] = $w;
			}
		}
		return $known;
	}

	private static function known_edits22($word) {
		$known = array();
		foreach(self::edits1($word) as $e1) {
			foreach(self::edits1($e1) as $e2) {
				if(array_key_exists($e2,self::$NWORDSTwo)) $known[$e2] = $e2;			
			}
		}
		return $known;
	}
	
	private static function known2(array $words) {
		$known = array();
		foreach($words as $w) {
			if(array_key_exists($w,self::$NWORDSTwo)) {
				$known[$w] = $w;
			}
		}
		return $known;
	}

	public static function correct($word) {
		$wordOne = substr($word, 0, strpos($word, " "));
		$wordTwo = substr($word, strpos($word, " "));
		$wordOne = trim($wordOne);
		$wordTwo = trim($wordTwo);
		$wordOne = strtolower($wordOne);
		$wordTwo = strtolower($wordTwo);
		if(empty(self::$NWORDS)) {
			if(!file_exists('serialized_dictionaryTwo_one.txt')) {
				$hashmap = array(); 
				$query = DictionaryTwo::model()->findAll();
				foreach ($query as $q) {
					$hashmap[substr($q->word, 0, strpos($q->word, " "))] = $q->id;
    			}
				self::$NWORDS = $hashmap;
				$fp = fopen("serialized_dictionaryTwo_one.txt","w+");
				fwrite($fp,serialize(self::$NWORDS));
				fclose($fp);
			} else {
				self::$NWORDS = unserialize(file_get_contents("serialized_dictionaryTwo_one.txt"));
			}
		}
		if(empty(self::$NWORDSTwo)) {
			if(!file_exists('serialized_dictionaryTwo_two.txt')) {
				$hashmap = array(); 
				$query = DictionaryTwo::model()->findAll();
				foreach ($query as $q) {
    				$hashmap[substr($q->word, strpos($q->word, " ")+1)] = $q->id;
    			}
				self::$NWORDSTwo = $hashmap;
				$fp = fopen("serialized_dictionaryTwo_two.txt","w+");
				fwrite($fp,serialize(self::$NWORDSTwo));
				fclose($fp);
			} else {
				self::$NWORDSTwo = unserialize(file_get_contents("serialized_dictionaryTwo_two.txt"));
			}
		}
		$firstArray = array();
		$secondArray = array();
		$result = array();
		if(self::known(array($wordOne))) {
			$firstArray[] = $wordOne;
		}elseif(($tmp_candidates = self::known_edits2($wordOne))) {
			foreach($tmp_candidates as $candidate) {
				$firstArray[] = $candidate;
			}
		}else {
			$firstArray[] = $wordOne;
		}
		if(self::known2(array($wordTwo))) {
			$secondArray[] = $wordTwo;
		}elseif(($tmp_candidates = self::known_edits22($wordTwo))) {
			foreach($tmp_candidates as $candidate) {
				$secondArray[] = $candidate;
			}
		}else {
			$secondArray[] = $wordTwo;
		}
		$query = DictionaryTwo::model()->findAll();
		foreach ($query as $q) {
			foreach ($firstArray as $f) {
				foreach ($secondArray as $s) {
					if($q->word===$f." ".$s)
						$result[] = $q->word;
				}
			}
		}
		return $result;
	}	
}

?>